using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace SV2Xml.Controls {
    /// <summary>
    /// Provides an object that represents a most recently used file menu.
    /// </summary>
    public partial class MostRecentlyUsedFileMenu : ToolStripMenuItem {
        private int maximumFileListSize = 5;

        /// <summary>
        /// 	<para>Initializes an instance of the <see cref="MostRecentlyUsedFileMenu"/> class.</para>
        /// </summary>
        public MostRecentlyUsedFileMenu() {
            InitializeComponent();
            this.Text = "Recent Files";
            // load the files from the data store
            this.Load();
            // set the state of the control (enabled/disabled)
            this.SetState();
        }

        
        /// <summary>
        /// Specifies the maximum number of files that can show up in the most recently used file list.
        /// </summary>
        public int MaximumFileListSize {
            get {
                return this.maximumFileListSize;
            }
            set {
                this.maximumFileListSize = value;
            }
        }

        /// <summary>
        /// Adds a file to the most recently used file list.
        /// </summary>
        /// <param name="path">The path to the file on disk.</param>
        public void AddFile(string path) {
            this.AddFile(path, true, true);
        }

        /// <summary>
        /// Adds a file to the most recently used file list.
        /// </summary>
        /// <param name="path">The path to the file on disk.</param>
        /// <param name="persist">Specifies if the file should be persisted to the data store.</param>
        /// <param name="renumber">Specifies if the action of adding the file to the list should refresh the numbering of the files in the list.</param>
        /// <exception cref="ArgumentNullException">
        /// 	<para>The argument <paramref name="path"/> is <langword name="null"/>.</para>
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// 	<para>The argument <paramref name="path"/> is out of range.</para>
        /// </exception>
        public void AddFile(string path, bool persist, bool renumber) {
            if (path == null) {
                throw new ArgumentNullException("path");
            }
            if (path.Length == 0) {
                throw new ArgumentOutOfRangeException("path");
            }

            // create a new file menu item
            Controls.MostRecentlyUsedFile file = new Controls.MostRecentlyUsedFile(path);
            file.Click += new EventHandler(file_Click);

            // first, remove the file from the list.  This step is necessary to take a file 
            // from the list and move it to the top (remove, then re-add).
            this.DropDownItems.Remove(file);

            // take the file and add it to the top of the list.
            this.DropDownItems.Insert(0, file);

            // determine if the number of items in the list will exceed the maximum number of files allowed.
            if (this.DropDownItems.Count > this.maximumFileListSize) {
                // there are too many files in the list, remove the last (oldest one).
                this.DropDownItems.RemoveAt(this.DropDownItems.Count - 1);
            }

            // if persist is specified, save the files to the data store
            if (persist) {
                this.Persist();
            }

            // set the state of the control
            this.SetState();

            // if renumber is specified, renumber the list.
            if (renumber) {
                this.NumberFiles();
            }
        }

        private void file_Click(object sender, EventArgs e) {
            this.OnFileClicked(((Controls.MostRecentlyUsedFile)sender).Path);
        }

        /// <summary>
        /// Adds numbering to the text display of the file in the list.
        /// </summary>
        private void NumberFiles() {
            for (int i = 0; i < this.DropDownItems.Count; i++) {
                StringBuilder builder = new StringBuilder();
                builder.Append(i + 1);
                builder.Append(". ");
                builder.Append(((Controls.MostRecentlyUsedFile)this.DropDownItems[i]).TruncatedFilePath);
                this.DropDownItems[i].Text = builder.ToString();
            }
        }

        /// <summary>
        /// Removes a file from the most recently used file list.
        /// </summary>
        /// <param name="path">The path to the file to remove.</param>
        public void RemoveFile(string path) {
            foreach (ToolStripMenuItem item in this.DropDownItems) {
                if (item is Controls.MostRecentlyUsedFile) {
                    if (((MostRecentlyUsedFile)item).Path.Equals(path)) {
                        this.DropDownItems.Remove(item);
                    }
                }
            }
            // set the state of the control.
            this.SetState();
        }

        /// <summary>
        /// Clears all recently used files from the most recently used file menu.
        /// </summary>
        public void Clear() {
            this.DropDownItems.Clear();
        }

        /// <summary>
        /// Sets the enabled/disbled state of the control based on the number of items added.
        /// </summary>
        private void SetState() {
            if (this.DropDownItems.Count == 0) {
                this.Enabled = false;
            } else {
                this.Enabled = true;
            }
        }

        /// <summary>
        /// Saves the most recently used file menu and its items to the data store.
        /// </summary>
        private void Persist() {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < this.DropDownItems.Count; i++ ) {
                if (this.DropDownItems[i] is Controls.MostRecentlyUsedFile) {
                    builder.Append(((MostRecentlyUsedFile)this.DropDownItems[i]).Path);
                    if (this.DropDownItems.Count > 1 && i < this.DropDownItems.Count -1) {
                        builder.Append(",");
                    }
                }
            }
            Properties.Settings.Default.Mruf = builder.ToString();
            Properties.Settings.Default.Save();
        }

        /// <summary>
        /// Loads the most recently used files from the data store.
        /// </summary>
        private void Load() {
            // clear out the existing drop down items
            this.Clear();
            // get the list of files from the config file
            string[] files = Properties.Settings.Default.Mruf.Split(new char[] { ',' });

            // if the config file has no value specified, then an empty string will be the first item in a 
            // one item sized array.  in this case, there is nothing to add to the menu.
            if (!files[0].Equals(string.Empty)) {
                for (int i = files.Length -1; i >= 0; i--) {
                    this.AddFile(files[i], false, false);
                }
            }
            // once the menu has been populated, number the menu items.
            this.NumberFiles();
        }

        public delegate void FileClickedEventHandler(object sender, string path);
        public event FileClickedEventHandler FileClicked;

        /// <summary>
        /// Delegate method for the FileClicked event.
        /// </summary>
        /// <param name="line">The line that was parsed.</param>
        public void OnFileClicked(string path) {
            if (FileClicked != null) {
                FileClicked(this, path);
            }
        }
    }
}